﻿using System;
using System.Collections.Generic;
using System.Text;
using MapCenterSystem.DataInfo;
using MapCenterSystem.DataAccess;
using MapCenterSystem.DefineType;

namespace MapCenterSytem.Process
{
    public class Node
    {
        public static NodeInfo GetNodeInfo(int node)
        {
            NodeService nodeService = new NodeService();
            return nodeService.GetNodeInfo(node);
        }

        private static bool InList(GraphNodeInfo node,List<GraphNodeInfo> lst )
        {
            foreach (GraphNodeInfo n in lst)
                if (n.Equals(node))
                    return true;
            return false;
        }

        private static int Heuristic(GraphNodeInfo node, GraphNodeInfo end)
        {
            GraphNodeService service = new GraphNodeService();
            return service.Distant(node, end);
        }

        private static List<NodeInfo> ShortestPath(List<GraphNodeInfo> lstClose)
        {
            List<NodeInfo> result = new List<NodeInfo>();
            int lastIndex = lstClose.Count - 1;
            NodeInfo nodeInfo = new NodeInfo();
            GraphNodeInfo end = lstClose[lastIndex];
            GraphNodeInfo start= lstClose[0];
            nodeInfo.Id = end.Id;
            nodeInfo.Location = end.Location;
            result.Add(nodeInfo);
            GraphNodeInfo node =end;
            while (!node.Equals(start))
            {
                node = node.Parent;
                NodeInfo temp= new NodeInfo();
                temp.Id = node.Id;
                temp.Location = node.Location;
                result.Add(temp);
            }
            return result;
        }

        public static NodeInfo GetNodeInfo(Coordinate location)
        {
            NodeService nodeService = new NodeService();
            return nodeService.GetNodeInfo(location);
        }

        public static List<NodeInfo> ShortestPath(NodeInfo from, NodeInfo end)
        {
            GraphNodeService nodeService = new GraphNodeService();
            GraphNodeInfo nodeStart = nodeService.GetGraphNodeInfo(from.Id);
            nodeStart.IsRoot = true;
            nodeStart.Length = 0;
            nodeStart.Parent = null;
            nodeStart.MovementCost();
            nodeStart.PathScoring();
            GraphNodeInfo nodeEnd = nodeService.GetGraphNodeInfo(end.Id);
            List<GraphNodeInfo> lstOpen = new List<GraphNodeInfo>();
            List<GraphNodeInfo> lstClose = new List<GraphNodeInfo>();
            lstOpen.Add(nodeStart);
            int count = 0;
            while (lstOpen.Count > 0 && count < 2000)
            {
                count++;
                GraphNodeInfo currentNode = new GraphNodeInfo(lstOpen[0]);
                lstClose.Add(currentNode);
                if (currentNode.Equals(nodeEnd))
                    return ShortestPath(lstClose);//tim thay
                lstOpen.RemoveAt(0);
                List<GraphNodeInfo> lstNodeRelate = nodeService.GetListNodeRelate(currentNode);
                foreach (GraphNodeInfo node in lstNodeRelate)
                {
                    if (InList(node, lstClose))
                        continue;
                    if (!InList(node, lstOpen))
                    {
                        node.Heuristic = Heuristic(node, nodeEnd);
                        node.IsRoot = false;
                        node.Parent = currentNode;
                        node.MovementCost();
                        node.PathScoring();
                        lstOpen.Add(node);
                    }
                    else
                    {
                        node.Heuristic = Heuristic(node, nodeEnd);
                        node.MovementCost();
                        node.PathScoring();//F;
                        node.IsRoot = false;
                        node.Parent = currentNode;// chueyn lai
                    }
                }
                lstOpen.Sort();
            }
            return null;
        }
    }
}
